#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
 
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/kdev_t.h>



#define DEVICE_NAME "mychar"
#define DEVICE_MINOR 0
#define DEVICE_MAJOR 100
#define DEVICE_COUNT 1

struct dev_device {
    dev_t devid;
    struct cdev cdev;
    // 添加设备相关的成员变量
    int major;
    int minor;
    struct class *class;
    struct device *device;
};

static struct dev_device my_device;

ssize_t cRead (struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {
    // 读取数据的逻辑
    return count;
}

ssize_t cWrite (struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
    char *kernel_buf = kmalloc(count, GFP_KERNEL);// 获取设备结构体指针
    // struct dev_device *my_dev = (struct dev_device *)filp->private_data;
    // kernel_buf = kmalloc(count, GFP_KERNEL);
    // if (!kernel_buf) {
    //     return -ENOMEM;
    // }
    // 将用户空间的数据复制到内核空间的kernel_buf
    if (copy_from_user(kernel_buf, buf, count)) {
        kfree(kernel_buf);
        return -EFAULT;
    }
    printk(KERN_INFO "Received %zu bytes from user space: %s", count, kernel_buf);
    // 在这里可以对复制到内核空间的数据进行处理
    kfree(kernel_buf);

    // 写入数据的逻辑
    return count;
}

int cOpen (struct inode *inode, struct file *filp) {
    filp->private_data = &my_device;
    // 打开设备的逻辑
    return 0;
}

int cRelease (struct inode *inode, struct file *filp) {
    // 关闭设备的逻辑
    return 0;
}

struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = cRead,
    .write = cWrite,
    .open = cOpen,
    .release = cRelease
};

static int my_dev_mod_init(void) {
    int ret;

    alloc_chrdev_region(&my_device.devid, DEVICE_MINOR, DEVICE_COUNT, DEVICE_NAME);
    my_device.devid = MKDEV(DEVICE_MAJOR, DEVICE_MINOR);
    // 注册字符设备
    ret = register_chrdev_region(my_device.devid, DEVICE_COUNT, DEVICE_NAME);
    if (ret < 0) {
        printk(KERN_ALERT "Failed to register character device\n");
        return ret;
    }
        // 初始化设备结构体
  
    my_device.major = MAJOR(my_device.devid);
    my_device.minor = MINOR(my_device.devid);

    printk("major = %d , minor = %d",my_device.major,my_device.minor);
    // 初始化 cdev
    cdev_init(&my_device.cdev, &fops);
    my_device.cdev.owner = THIS_MODULE;

    // 添加 cdev
    ret = cdev_add(&my_device.cdev, my_device.devid, DEVICE_COUNT);
    if (ret < 0) {
        printk(KERN_ALERT "Failed to add character device\n");
        unregister_chrdev_region(my_device.devid, DEVICE_COUNT);
        return ret;
    }

    // 创建设备节点
    my_device.class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(my_device.class)) {
        printk(KERN_ALERT "Failed to create device class\n");
        goto err_class;
        return PTR_ERR(my_device.class);
    }
    my_device.device = device_create(my_device.class, NULL, my_device.devid, NULL, DEVICE_NAME);
    if (IS_ERR(my_device.device)) {
        printk(KERN_ALERT "Failed to create device\n");
        goto err_device;
        return PTR_ERR(my_device.device);
    }
    printk(KERN_INFO "Character device driver initialized\n");
    return 0;

err_class:
    cdev_del(&my_device.cdev);
    unregister_chrdev_region(my_device.devid, DEVICE_COUNT);
    return ret;

err_device:
    class_destroy(my_device.class);
    goto err_class;
    return ret;
}

static void my_dev_mod_exit(void) {
    dev_t devno = my_device.devid;

    // 删除 cdev
    cdev_del(&my_device.cdev);

    // 注销字符设备
    unregister_chrdev_region(devno, DEVICE_COUNT);
    // 销毁设备结构体
    device_destroy(my_device.class, devno);
    class_destroy(my_device.class);

    printk(KERN_INFO "Character device driver exited\n");
}

module_init(my_dev_mod_init);
module_exit(my_dev_mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wlz"); // 添加作者信息
